/* JFlex file, Oberon-0 Scanner Generator */
import java_cup.runtime.*;
import java.io.*;

%%

%class OberonScanner /*Name of the Scanner*/
%line
%column
%cup
%unicode
%ignorecase


%{
  /**
   * Runs the scanner on input files.
   *
   * This is a standalone scanner, it will print any unmatched
   * text to System.out unchanged.
   *
   * @param argv   the command line, contains the filenames to run
   *               the scanner on.
   */
  public static void main(String argv[]) {
    if (argv.length == 0) {      System.out.println("Usage : java Subst <inputfile>");
    }
    else {
      OberonScanner s = null;      try {
        s = new OberonScanner( new java.io.FileReader(argv[0]) );        Symbol smb;
        while (true) {
          smb = s.next_token();
          if (smb == null) break;
          System.out.print(" \"" + smb.value.toString() + "\" ");
        }
      }      catch (java.io.FileNotFoundException e) {
        System.out.println("File not found : \""+argv[0]+"\"");
      }      catch (java.io.IOException e) {
        System.out.println("IO error scanning file \""+argv[0]+"\"");
        System.out.println(e);      }
      catch (Exception e) {}
      System.out.println();
    }  }
  public static void init(){}
  private Symbol symbol(int type)
  {
    return new Symbol(type, yyline, yycolumn);
  }
  private Symbol symbol(int type, Object value)
  {
    return new Symbol(type, yyline, yycolumn, value);
  }
%}

/* Blanks */
LineTerminator = \r | \n | \r\n
WhiteSpace     = {LineTerminator} | [ \t\f]
BlankLine      = [WhiteSpace*]LineTerminator

/* Comments */
TraditionalComment = "(*" [^%] ~"*)" | "/*" + "*" + "/"
Comment            = {TraditionalComment}

Identifier = [:jletter:][:jletterdigit:]*{0,23}/* identifiers should not be longer than 24 characters */
DecIntegerLiteral = 0 | [1-9][0-9]*{0,11}
OctIntegerLiteral = 0[0-7]*{0,11}


%%

/* Keywords */
<YYINITIAL> "BOOLEAN"   { //System.out.println("BOOLEAN");	
                        return symbol(sym.IDENTIFIER, new String("BOOLEAN"));  }
<YYINITIAL> "INTEGER"	{ //System.out.println("INTEGER");
                        return symbol(sym.IDENTIFIER, new String("INTEGER"));  }
<YYINITIAL> "MODULE"    { //System.out.println("MODULE");
                        return symbol(sym.MODULE, new String("MODULE"));       }
<YYINITIAL> "BEGIN"     { //System.out.println("BEGIN");
                        return symbol(sym.BEGIN, new String("BEGIN"));         }
<YYINITIAL> "END"       { //System.out.println("END");
                        return symbol(sym.END, new String("END"));             }
<YYINITIAL> "CONST"     { //System.out.println("CONST");
                        return symbol(sym.CONST, new String("CONST"));         }
<YYINITIAL> "TYPE"      { //System.out.println("TYPE");
                        return symbol(sym.TYPE, new String("TYPE"));           }
<YYINITIAL> "VAR"       { //System.out.println("VAR");
                        return symbol(sym.VAR, new String("VAR"));             }
<YYINITIAL> "PROCEDURE" { //System.out.println("PROCEDURE");
                        return symbol(sym.PROCEDURE, new String("PROCEDURE")); }
<YYINITIAL> "RECORD"    { //System.out.println("RECORD");
                        return symbol(sym.RECORD, new String("RECORD"));       }
<YYINITIAL> "WHILE"     { //System.out.println("WHILE");
                        return symbol(sym.WHILE, new String("WHILE"));         }
<YYINITIAL> "IF"        { //System.out.println("IF");
                        return symbol(sym.IF, new String("IF"));               }
<YYINITIAL> "ELSE"      { //System.out.println("ELSE");
                        return symbol(sym.ELSE, new String("ELSE"));           }
<YYINITIAL> "DO"        { //System.out.println("DO");
                        return symbol(sym.DO, new String("DO"));               }
<YYINITIAL> "ARRAY"     { //System.out.println("ARRAY");
                        return symbol(sym.ARRAY, new String("ARRAY"));         }
<YYINITIAL> "OF"        { //System.out.println("OF");
                        return symbol(sym.OF, new String("OF"));               }
<YYINITIAL> "ELSIF"     { //System.out.println("ELSIF");
                        return symbol(sym.ELSIF, new String("ELSIF"));         }
<YYINITIAL> "THEN"      { //System.out.println("THEN");
                        return symbol(sym.THEN, new String("THEN"));           }
<YYINITIAL> "DIV"       { //System.out.println("DIV");
                        return symbol(sym.DIV, new String("DIV"));             }
<YYINITIAL> "MOD"       { //System.out.println("MOD");
                        return symbol(sym.MOD, new String("MOD"));             }
<YYINITIAL> "OR"        { //System.out.println("OR");
                        return symbol(sym.OR, new String("OR"));               }

<YYINITIAL> {
    /* Identifiers */
    {Identifier}        { //System.out.println(new String(yytext()));
                        return symbol(sym.IDENTIFIER, new String(yytext()).toLowerCase()); }

    /* Literals */
    {DecIntegerLiteral} { //System.out.println(new Integer(yytext()));
                        return symbol(sym.NUMBER, new Integer(yytext())); }
    {OctIntegerLiteral} { //System.out.println(new Integer(yytext())); 
                        return symbol(sym.NUMBER, new Integer(yytext())); }

    /* Operators */
    ";"                 { //System.out.println(";");
                        return symbol(sym.SEMI, new String(";"));         }
    "."                 { //System.out.println(".");
                        return symbol(sym.DOT, new String("."));          }
    "="                 { //System.out.println("="); 
                        return symbol(sym.EQ, new String("="));           }
    ":"                 { //System.out.println(":");
                        return symbol(sym.COLON, new String(":"));        }
    "+"                 { //System.out.println("+");
                        return symbol(sym.PLUS, new String("+"));         }
    "-"                 { //System.out.println("-");
                        return symbol(sym.SUBSTRACT, new String("-"));    }
    "*"                 { //System.out.println("*");
                        return symbol(sym.MULTIPLY, new String("*"));     }
    "("                 { //System.out.println("(");
                        return symbol(sym.LPAREN, new String("("));       }
    ")"                 { //System.out.println(")");
                        return symbol(sym.RPAREN, new String(")"));       }
    ","                 { //System.out.println(",");
                        return symbol(sym.COMMA, new String(","));        }
    ":="                { //System.out.println(":=");
                        return symbol(sym.EVALUATE, new String(":="));    }
    "#"                 { //System.out.println("#");
                        return symbol(sym.NOTEQUAL, new String("#"));     }
    ">="                { //System.out.println(">=");
                        return symbol(sym.GRTEQU, new String(">="));      }
    "<="                { //System.out.println("<=");
                        return symbol(sym.LESEQU, new String("<="));      }
    ">"                 { //System.out.println(">");
                        return symbol(sym.GREATER, new String(">"));      }
    "<"                 { //System.out.println("<");
                        return symbol(sym.LESS, new String("<"));         }
    "&"                 { //System.out.println("&");
                        return symbol(sym.AND, new String("&"));          }
    "~"                 { //System.out.println("~");
                        return symbol(sym.NOT, new String("~"));          }
    "["                 { //System.out.println("[");
                        return symbol(sym.LBRACKET, new String("["));     }
    "]"                 { //System.out.println("]");
                        return symbol(sym.RBRACKET, new String("]"));     }

    /* Comments */
    {Comment}           { //System.out.println("Comment");
                        /* ingore */ }

    /* Whitespace */
    {WhiteSpace}        { /* ingore */ }

    /* BlankLine */
    {BlankLine}         { /* ingore */ }
}
